﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GISCore.Geometry.Intersectors
{
    public class AllPairsIntersector : IIntersector
    {
        public AllPairsIntersector() { }

        public IEnumerable<IntersectPoint> Intersect(IEnumerable<Line> lines)
        {
            Debug.Assert(lines != null);
            IntersectPoint point = default(IntersectPoint);
            
            /* there is a bug so commented , finds duplicate intersection pts */
            /*
            var points = from line1 in lines
                         from line2 in lines
                         where _intersect(line1, line2, out point)
                         select point;
            */

            List<IntersectPoint> points = new List<IntersectPoint>();
            
            /* classify the lines on the basis of layers */
            List<Line> lineListBaseLayer = new List<Line>();
            List<Line> lineListTargetLayer = new List<Line>();

            foreach (var line in lines)
            {
                if (line.label == Constants.baseLayerId)
                {
                    lineListBaseLayer.Add(line);
                }
                else
                {
                    lineListTargetLayer.Add(line);
                }
            }


            foreach (var lineFromBase in lineListBaseLayer)
            {
                foreach (var lineFromTarget in lineListTargetLayer)
                {
                    if (true == _intersect(lineFromBase, lineFromTarget, out point))
                    {
                        points.Add(point);
                    }
                }
            }
            return points;
        }

        /* If intersection point found then add the lines to the point */
        private bool _intersect(Line line1, Line line2, out IntersectPoint point)
        {
            bool intersected = false;
            
            if(line1.label==line2.label)
            {
             point = default(IntersectPoint);
             return intersected;
            }

            if (line1.getIntersect(line2, out point) == Intersection.True)
            {
                    intersected = true;
                    /* adding the lines to the intersect point found */
                    if (line1.parent != null)
                    {
                        point.inComingLine = line1.parent;
                    }
                    else
                    {
                        point.inComingLine = line1;
                    }

                    if (line2.parent != null)
                    {
                        point.outGoingLine = line2.parent;
                    }
                    else
                    {
                        point.outGoingLine = line2;
                    }

                    /* add the intersection point to the intersecting lines */
                    line1.addIntersectPoint(point);
                    line2.addIntersectPoint(point);
                    /* add the intersection point to its parent intersecting lines */
                    /* null check is required because some lines are not broken down by
                     * grid lines ie full line occupies a grid cell 
                     */
                    if (line1.parent != null)
                    {
                        line1.parent.addIntersectPoint(point);
                    }
                    if (line2.parent != null)
                    {
                        line2.parent.addIntersectPoint(point);
                    }
            }
            
            return intersected;
        }

    }
}
